﻿// Author: Daniele Giardini - http://www.demigiant.com
// Created: 2015/01/29 12:57

using FT.Tweening.Core;
using FT.Tweening.Core.Easing;
using UnityEngine;
namespace FT.Tweening
{
    /// <summary>
    /// Creates virtual tweens that can be used to change other elements via their OnUpdate calls
    /// </summary>
    public static class FrameVirtual
    {
        #region Virtual Tweens

        /// <summary>
        /// Tweens a virtual float.
        /// You can add regular settings to the generated tween,
        /// but do not use <code>OnUpdate</code> or you will overwrite the onVirtualUpdate parameter
        /// </summary>
        /// <param name="from">The value to start from</param>
        /// <param name="to">The value to tween to</param>
        /// <param name="duration">The duration of the tween</param>
        /// <param name="onVirtualUpdate">A callback which must accept a parameter of type float, called at each update</param>
        public static GuidTweener Float(float from, float to, int duration, TweenCallback<float> onVirtualUpdate)
        {
            float val = from;
            GuidTweener t = FrameTween.To(() => val, x => val = x, to, duration);
            t.Value.OnUpdate(() => onVirtualUpdate(val));
            return t;
        }
        /// <summary>
        /// Tweens a virtual int.
        /// You can add regular settings to the generated tween,
        /// but do not use <code>OnUpdate</code> or you will overwrite the onVirtualUpdate parameter
        /// </summary>
        /// <param name="from">The value to start from</param>
        /// <param name="to">The value to tween to</param>
        /// <param name="duration">The duration of the tween</param>
        /// <param name="onVirtualUpdate">A callback which must accept a parameter of type int, called at each update</param>
        public static GuidTweener Int(int from, int to, int duration, TweenCallback<int> onVirtualUpdate)
        {
            int val = from;
            GuidTweener t = FrameTween.To(() => val, x => val = x, to, duration);
            t.Value.OnUpdate(() => onVirtualUpdate(val));
            return t;
        }
        /// <summary>
        /// Tweens a virtual Vector2.
        /// You can add regular settings to the generated tween,
        /// but do not use <code>OnUpdate</code> or you will overwrite the onVirtualUpdate parameter
        /// </summary>
        /// <param name="from">The value to start from</param>
        /// <param name="to">The value to tween to</param>
        /// <param name="duration">The duration of the tween</param>
        /// <param name="onVirtualUpdate">A callback which must accept a parameter of type Vector3, called at each update</param>
        public static GuidTweener Vector2(Vector2 from, Vector2 to, int duration, TweenCallback<Vector2> onVirtualUpdate)
        {
            Vector2 val = from;
            GuidTweener t = FrameTween.To(() => val, x => val = x, to, duration);
            t.Value.OnUpdate(() => onVirtualUpdate(val));
            return t;
        }
        /// <summary>
        /// Tweens a virtual Vector3.
        /// You can add regular settings to the generated tween,
        /// but do not use <code>OnUpdate</code> or you will overwrite the onVirtualUpdate parameter
        /// </summary>
        /// <param name="from">The value to start from</param>
        /// <param name="to">The value to tween to</param>
        /// <param name="duration">The duration of the tween</param>
        /// <param name="onVirtualUpdate">A callback which must accept a parameter of type Vector3, called at each update</param>
        public static GuidTweener Vector3(Vector3 from, Vector3 to, int duration, TweenCallback<Vector3> onVirtualUpdate)
        {
            Vector3 val = from;
            GuidTweener t = FrameTween.To(() => val, x => val = x, to, duration);
            t.Value.OnUpdate(() => onVirtualUpdate(val));
            return t;
        }
        /// <summary>
        /// Tweens a virtual Color.
        /// You can add regular settings to the generated tween,
        /// but do not use <code>OnUpdate</code> or you will overwrite the onVirtualUpdate parameter
        /// </summary>
        /// <param name="from">The value to start from</param>
        /// <param name="to">The value to tween to</param>
        /// <param name="duration">The duration of the tween</param>
        /// <param name="onVirtualUpdate">A callback which must accept a parameter of type Color, called at each update</param>
        public static GuidTweener Color(Color from, Color to, int duration, TweenCallback<Color> onVirtualUpdate)
        {
            Color val = from;
            GuidTweener t = FrameTween.To(() => val, x => val = x, to, duration);
            t.Value.OnUpdate(() => onVirtualUpdate(val));
            return t;
        }

        #endregion

        #region Virtual Functions

        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        public static float EasedValue(float from, float to, float lifetimePercentage, Ease easeType)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, FrameTween.defaultEaseOvershootOrAmplitude, FrameTween.defaultEasePeriod);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        /// <param name="overshoot">Eventual overshoot to use with Back ease</param>
        public static float EasedValue(float from, float to, float lifetimePercentage, Ease easeType, float overshoot)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, overshoot, FrameTween.defaultEasePeriod);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        /// <param name="amplitude">Eventual amplitude to use with Elastic easeType</param>
        /// <param name="period">Eventual period to use with Elastic easeType</param>
        public static float EasedValue(float from, float to, float lifetimePercentage, Ease easeType, float amplitude, float period)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, amplitude, period);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeCurve">The AnimationCurve to use for ease</param>
        public static float EasedValue(float from, float to, float lifetimePercentage, AnimationCurve easeCurve)
        {
            return from + (to - from) * EaseManager.Evaluate(Ease.INTERNAL_Custom, new EaseCurve(easeCurve).Evaluate, lifetimePercentage, 1, FrameTween.defaultEaseOvershootOrAmplitude, FrameTween.defaultEasePeriod);
        }

        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, Ease easeType)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, FrameTween.defaultEaseOvershootOrAmplitude, FrameTween.defaultEasePeriod);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        /// <param name="overshoot">Eventual overshoot to use with Back ease</param>
        public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, Ease easeType, float overshoot)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, overshoot, FrameTween.defaultEasePeriod);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeType">The type of ease</param>
        /// <param name="amplitude">Eventual amplitude to use with Elastic easeType</param>
        /// <param name="period">Eventual period to use with Elastic easeType</param>
        public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, Ease easeType, float amplitude, float period)
        {
            return from + (to - from) * EaseManager.Evaluate(easeType, null, lifetimePercentage, 1, amplitude, period);
        }
        /// <summary>Returns a value based on the given ease and lifetime percentage (0 to 1)</summary>
        /// <param name="from">The value to start from when lifetimePercentage is 0</param>
        /// <param name="to">The value to reach when lifetimePercentage is 1</param>
        /// <param name="lifetimePercentage">The time percentage (0 to 1) at which the value should be taken</param>
        /// <param name="easeCurve">The AnimationCurve to use for ease</param>
        public static Vector3 EasedValue(Vector3 from, Vector3 to, float lifetimePercentage, AnimationCurve easeCurve)
        {
            return from + (to - from) * EaseManager.Evaluate(Ease.INTERNAL_Custom, new EaseCurve(easeCurve).Evaluate, lifetimePercentage, 1, FrameTween.defaultEaseOvershootOrAmplitude, FrameTween.defaultEasePeriod);
        }

        /// <summary>Fires the given callback after the given time.</summary>
        /// <param name="delay">Callback delay</param>
        /// <param name="callback">Callback to fire when the delay has expired</param>
        /// <param name="ignoreTimeScale">If TRUE (default) ignores Unity's timeScale</param>
        public static GuidTween DelayedCall(int delay, TweenCallback callback)
        {
            GuidSequence t= FrameTween.Sequence();
            t.Value.AppendInterval(delay).OnStepComplete(callback).SetAutoKill(true);
            return t;
        }

        #endregion
    }
}



